package com.test.framework.rest;

import com.test.utils.Logger;
import okhttp3.*;
import okio.Buffer;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Http请求函数封装类
 */
public class RestAPIBase {
    static long timeout = 90; //seconds

    public void setTimeout(int newTimeout){
        timeout=newTimeout;
    }

    protected Map<String, Object> Get(String url, Map<String, String> header, Map<String, String> params) throws IOException, JSONException {
        return CallMethod("get", url, header, params, null);
    }

    protected Map<String, Object> Delete(String url, Map<String, String> header, Map<String, String> params) throws IOException, JSONException {
        return CallMethod("delete", url, header, params, null);
    }

    protected Map<String, Object> Post(String url, Map<String, String> header, Map<String, String> params, String json) throws IOException, JSONException {
        RequestBody body = null;
        if (json != null) {
            body = RequestBody.create(MediaType.parse("application/json"), json);
        }
        return CallMethod("post", url, header, params, body);
    }

    protected Map<String, Object> Post(String url, Map<String, String> header, File file) throws IOException, JSONException {
        RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                .addFormDataPart("app", file.getName(),
                        RequestBody.create(MediaType.parse("application/octet-stream"), file))
                .addFormDataPart("metadata", "{\"build_commit\": \"" + file.getName() + "\"}")
                .build();

        return CallMethod("post", url, header, null, body);
    }

    private Map<String, Object> CallMethod(String method, String url, Map<String, String> header, Map<String, String> params
            , RequestBody body) throws IOException, JSONException {
        //处理 Header
        if (header == null) {
            header = new HashMap<>();
        }
        if (!header.containsKey("Content-Type")) {
            header.put("Content-Type", "application/json");
        }

        //处理 Params
        HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
        if (params != null) {
            for (String key : params.keySet()) {
                urlBuilder.addQueryParameter(key, params.get(key));
            }
        }

        Request request = null;
        switch (method.toLowerCase()) {
            case "get":
                request = new Request.Builder()
                        .url(urlBuilder.build().toString())
                        .headers(Headers.of(header))
                        .get()
                        .build();
                break;
            case "post":
                if(body == null){
                    body = RequestBody.create(null, new byte[]{});
                }
                request = new Request.Builder()
                        .url(urlBuilder.build().toString())
                        .headers(Headers.of(header))
                        .post(body)
                        .build();
                break;
            case "delete":
                request = new Request.Builder()
                        .url(urlBuilder.build().toString())
                        .headers(Headers.of(header))
                        .delete()
                        .build();
                break;
            default:
                break;
        }

        // Request 日志输出
        if (header.containsKey("Content-Type") && header.get("Content-Type").equalsIgnoreCase("application/json")) {
            Logger.info(request.method() + " url: " + request.url() + " headers: " + header + " params: " + params
                    + " body: " + requestBodyToString(request.body()));
        } else if (header.containsKey("Content-Type") && header.get("Content-Type").equalsIgnoreCase("application/file")) {
            Logger.info(request.method() + " url: " + request.url() + " headers: " + header + " params: " + params
                    + " files: file stream ...");
        }
        OkHttpClient client = new OkHttpClient().newBuilder()
                .callTimeout(timeout, TimeUnit.SECONDS)
                .connectTimeout(timeout, TimeUnit.SECONDS)
                .readTimeout(timeout, TimeUnit.SECONDS)
                .writeTimeout(timeout, TimeUnit.SECONDS)
                .build();
        Response response = client.newCall(request).execute();
        int respCode = response.code();
        JSONObject respBody = new JSONObject(response.body().string());

        //Response 日志输出
        Logger.info("Response " + respCode + ": " + respBody);

        HashMap<String, Object> ret = new HashMap<>();
        ret.put("code", respCode);
        ret.put("body", respBody);
        return ret;
    }

    private String requestBodyToString(RequestBody requestBody) throws IOException {
        if (requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            return buffer.readUtf8();
        }
        return null;
    }
}